//////////////////////////////////////////ok
#include"stdafx.h"

#include "bochs.h"



void IA32_CPU::XCHG_ERXEAX(Ia32_Instruction_c *i)
{
   Bit32u temp32 = EAX;
   EAX =  gen_reg[i->opcodeReg()].dword.erx;
   gen_reg[i->opcodeReg()].dword.erx = temp32;

}

void IA32_CPU::MOV_ERXId(Ia32_Instruction_c *i)
{
  IA32_WRITE_32BIT_REGZ(i->opcodeReg(), i->Id());
}

void IA32_CPU::MOV_EEdGd(Ia32_Instruction_c *i)
{
  write_virtual_dword(i->seg(), IA32_RMAddr(i), &IA32_READ_32BIT_REG(i->nnn()));
}

void IA32_CPU::MOV_EGdGd(Ia32_Instruction_c *i)
{
  Bit32u op2_32 = IA32_READ_32BIT_REG(i->nnn());
  IA32_WRITE_32BIT_REGZ(i->rm(), op2_32);
}

void IA32_CPU::MOV_GdEGd(Ia32_Instruction_c *i)
{
  Bit32u op2_32 = IA32_READ_32BIT_REG(i->rm());
  IA32_WRITE_32BIT_REGZ(i->nnn(), op2_32);
}

void IA32_CPU::MOV_GdEEd(Ia32_Instruction_c *i)
{
  read_virtual_dword(i->seg(), IA32_RMAddr(i), &IA32_READ_32BIT_REG(i->nnn()));
  IA32_CLEAR_64BIT_HIGH(i->nnn());
}

void IA32_CPU::LEA_GdM(Ia32_Instruction_c *i)
{
  if (i->modC0()) 
  {
    UndefinedOpcode(i);
  }
  IA32_WRITE_32BIT_REGZ(i->nnn(), IA32_RMAddr(i));
}

void IA32_CPU::MOV_EAXOd(Ia32_Instruction_c *i)
{
  read_virtual_dword(i->seg(), i->Id(), &EAX);
  IA32_CLEAR_64BIT_HIGH(IA32_64BIT_REG_RAX);
}

void IA32_CPU::MOV_OdEAX(Ia32_Instruction_c *i)
{
  write_virtual_dword(i->seg(), i->Id(), &EAX);
}

void IA32_CPU::MOV_EdId(Ia32_Instruction_c *i)
{
  Bit32u op2_32 = i->Id();

  if (i->modC0()) 
  {
    IA32_WRITE_32BIT_REGZ(i->rm(), op2_32);
  }
  else 
  {
    write_virtual_dword(i->seg(), IA32_RMAddr(i), &op2_32);
  }
}

void IA32_CPU::MOVZX_GdEb(Ia32_Instruction_c *i)
{
  Bit8u  op2_8;

  if (i->modC0()) 
  {
    op2_8 = IA32_READ_8BIT_REGx(i->rm(),i->extend8bitL());
  }
  else 
  {
    read_virtual_byte(i->seg(), IA32_RMAddr(i), &op2_8);
  }

  IA32_WRITE_32BIT_REGZ(i->nnn(), (Bit32u) op2_8);
}

void IA32_CPU::MOVZX_GdEw(Ia32_Instruction_c *i)
{
  Bit16u op2_16;

  if (i->modC0()) 
  {
    op2_16 = IA32_READ_16BIT_REG(i->rm());
  }
  else 
  {
    read_virtual_word(i->seg(), IA32_RMAddr(i), &op2_16);
  }

  IA32_WRITE_32BIT_REGZ(i->nnn(), (Bit32u) op2_16);
}

void IA32_CPU::MOVSX_GdEb(Ia32_Instruction_c *i)
{
  Bit8u op2_8;

  if (i->modC0()) 
  {
    op2_8 = IA32_READ_8BIT_REGx(i->rm(),i->extend8bitL());
  }
  else 
  {
    read_virtual_byte(i->seg(), IA32_RMAddr(i), &op2_8);
  }

  IA32_WRITE_32BIT_REGZ(i->nnn(), (Bit8s) op2_8);
}

void IA32_CPU::MOVSX_GdEw(Ia32_Instruction_c *i)
{
  Bit16u op2_16;

  if (i->modC0()) 
  {
    op2_16 = IA32_READ_16BIT_REG(i->rm());
  }
  else 
  {
    read_virtual_word(i->seg(), IA32_RMAddr(i), &op2_16);
  }

  IA32_WRITE_32BIT_REGZ(i->nnn(), (Bit16s) op2_16);
}


void IA32_CPU::XCHG_EdGd(Ia32_Instruction_c *i)
{
  Bit32u op2_32, op1_32;

  op2_32 = IA32_READ_32BIT_REG(i->nnn());
  /* op1_32 is a register or memory reference */
  if (i->modC0()) 
  {
    op1_32 = IA32_READ_32BIT_REG(i->rm());
    IA32_WRITE_32BIT_REGZ(i->rm(), op2_32);
  }
  else 
  {
    read_RMW_virtual_dword(i->seg(), IA32_RMAddr(i), &op1_32);
    write_RMW_virtual_dword(op2_32);
  }
  IA32_WRITE_32BIT_REGZ(i->nnn(), op1_32);
}

void IA32_CPU::CMOV_GdEd(Ia32_Instruction_c *i)
{
  bx_bool condition = 0;
  Bit32u op2_32;
  switch (i->b1()) 
  {
    // CMOV opcodes:
    case 0x140: condition = get_OF(); break;
    case 0x141: condition = !get_OF(); break;
    case 0x142: condition = get_CF(); break;
    case 0x143: condition = !get_CF(); break;
    case 0x144: condition = get_ZF(); break;
    case 0x145: condition = !get_ZF(); break;
    case 0x146: condition = get_CF() || get_ZF(); break;
    case 0x147: condition = !get_CF() && !get_ZF(); break;
    case 0x148: condition = get_SF(); break;
    case 0x149: condition = !get_SF(); break;
    case 0x14A: condition = get_PF(); break;
    case 0x14B: condition = !get_PF(); break;
    case 0x14C: condition = getB_SF() != getB_OF(); break;
    case 0x14D: condition = getB_SF() == getB_OF(); break;
    case 0x14E: condition = get_ZF() || (getB_SF() != getB_OF()); break;
    case 0x14F: condition = !get_ZF() && (getB_SF() == getB_OF()); break;
    default:
		break;
  }

  if (i->modC0()) 
  {
    op2_32 = IA32_READ_32BIT_REG(i->rm());
  }
  else 
  {
    read_virtual_dword(i->seg(), IA32_RMAddr(i), &op2_32);
  }

  if (condition) 
  {
    IA32_WRITE_32BIT_REGZ(i->nnn(), op2_32);
  }
}
